home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 001 / fue / c / file < prev    next >
Text File  |  1991-06-08  |  45KB  |  1,354 lines

  1. /*      FILE.C:   for MicroEMACS
  2.  
  3.         The routines in this file handle the reading, writing
  4.         and lookup of disk files.  All of details about the
  5.         reading and writing of the disk are in "fileio.c".
  6.  
  7. */
  8.  
  9. /*      Modifications:
  10.         12-Sep-89       Mike Burrow (INMOS)     Added folding.
  11.         11-Oct-89       Bob Green (INMOS)       Added dynamic fold info tables.
  12. */
  13.  
  14.  
  15. /*{{{  include files*/
  16.  
  17. #include        <stdio.h>
  18. #include        <string.h>
  19. #include        "estruct.h"
  20. #include        "etype.h"
  21. #include        "edef.h"
  22. #include        "elang.h"
  23.  
  24. /*}}}*/
  25.  
  26. /*{{{  PASCAL NEAR fileread(f, n)*/
  27. PASCAL NEAR fileread(f, n)
  28.  
  29. /*
  30.  * Read a file into the current
  31.  * buffer. This is really easy; all you do is
  32.  * find the name of the file, and call the standard
  33.  * "read a file into the current buffer" code.
  34.  * Bound to "C-X C-R".
  35.  */
  36.  
  37. int f, n;       /* default and numeric arguments (unused) */
  38.  
  39. {
  40.         register int s; /* status return */
  41.         char *fname;    /* file name to read */
  42.  
  43.         if (restflag)           /* don't allow this command if restricted */
  44.                 return(resterr());
  45.  
  46.         if ((fname = gtfilename(TEXT131)) == NULL)
  47. /*                              "Read file" */
  48.                 return(FALSE);
  49.  
  50.         /* exit any folds, so we overwrite the whole buffer */
  51.         exitallfolds();
  52.         return(readin(fname, TRUE));
  53. }
  54. /*}}}*/
  55.  
  56. /*{{{  PASCAL NEAR insfile(f, n)*/
  57. PASCAL NEAR insfile(f, n)
  58. /*
  59.  * Insert a file into the current
  60.  * buffer. This is really easy; all you do it
  61.  * find the name of the file, and call the standard
  62.  * "insert a file into the current buffer" code.
  63.  * Bound to "C-X C-I".
  64.  */
  65. {
  66.         register int    s;
  67.         char *fname;    /* file name */
  68.  
  69.         if (restflag)           /* don't allow this command if restricted */
  70.                 return(resterr());
  71.         if (curbp->b_mode&MDVIEW)      /* don't allow this command if  */
  72.                 return(rdonly());       /* we are in read only mode     */
  73.  
  74.         if ((fname = gtfilename(TEXT132)) == NULL) 
  75. /*                              "Insert file" */
  76.                 return(FALSE);
  77.         return(ifile(fname));
  78. }
  79. /*}}}*/
  80.  
  81. /*{{{  PASCAL NEAR filefind(f, n)*/
  82. PASCAL NEAR filefind(f, n)
  83.  
  84. /*
  85.  * Select a file for editing.
  86.  * Look around to see if you can find the
  87.  * fine in another buffer; if you can find it
  88.  * just switch to the buffer. If you cannot find
  89.  * the file, create a new buffer, read in the
  90.  * text, and switch to the new buffer.
  91.  * Bound to C-X C-F.
  92.  */
  93. {
  94.         char *fname;    /* file user wishes to find */  /* file name */
  95.         register int s;         /* status return */
  96.  
  97.         if (restflag)           /* don't allow this command if restricted */
  98.                 return(resterr());
  99.  
  100.         if ((fname = gtfilename(TEXT133)) == NULL) 
  101. /*                              "Find file" */
  102.                 return(FALSE);
  103.         return(getfile(fname, TRUE));
  104. }
  105. /*}}}*/
  106.  
  107. /*{{{  PASCAL NEAR viewfile(f, n)    - visit a file in VIEW mode*/
  108. PASCAL NEAR viewfile(f, n)      /* visit a file in VIEW mode */
  109. {
  110.         char *fname;    /* file user wishes to find */  /* file name */
  111.         register int s; /* status return */
  112.  
  113.         if (restflag)           /* don't allow this command if restricted */
  114.                 return(resterr());
  115.  
  116.         if ((fname = gtfilename(TEXT134)) == NULL) 
  117. /*                              "View file" */
  118.                 return(FALSE);
  119.         s = getfile(fname, FALSE);
  120.         if (s) {        /* if we succeed, put it in view mode */
  121.                 curwp->w_bufp->b_mode |= MDVIEW;
  122.                 upmode();
  123.         }
  124.         return(s);
  125. }
  126. /*}}}*/
  127.  
  128. #if     CRYPT
  129. /*{{{  PASCAL NEAR resetkey()  - reset the encryption key if needed */
  130. PASCAL NEAR resetkey()  /* reset the encryption key if needed */
  131.  
  132. {
  133.         register int s; /* return status */
  134.  
  135.         /* turn off the encryption flag */
  136.         cryptflag = FALSE;
  137.  
  138.         /* if we are in crypt mode */
  139.         if (curbp->b_mode & MDCRYPT) {
  140.                 if (curbp->b_key[0] == 0) {
  141.                         s = setekey(FALSE, 0);
  142.                         if (s != TRUE)
  143.                                 return(s);
  144.                 }
  145.  
  146.                 /* let others know... */
  147.                 cryptflag = TRUE;
  148.  
  149.                 /* and set up the key to be used! */
  150.                 /* de-encrypt it */
  151.                 crypt((char *)NULL, 0);
  152.                 crypt(curbp->b_key, strlen(curbp->b_key));
  153.  
  154.                 /* re-encrypt it...seeding it to start */
  155.                 crypt((char *)NULL, 0);
  156.                 crypt(curbp->b_key, strlen(curbp->b_key));
  157.         }
  158.  
  159.         return(TRUE);
  160. }
  161. /*}}}*/
  162. #endif
  163.  
  164. /*{{{  PASCAL NEAR getfile(fname, lockfl)*/
  165. PASCAL NEAR getfile(fname, lockfl)
  166.  
  167. char fname[];           /* file name to find */
  168. int lockfl;             /* check the file for locks? */
  169.  
  170. {
  171.         register BUFFER *bp;
  172.         register LINE   *lp;
  173.         register int    i;
  174.         register int    s;
  175.         register int cmark;     /* current mark */
  176.         char bname[NBUFN];      /* buffer name to put file */
  177.  
  178. #if     MSDOS | OS2 | AOSVS | RISCOS
  179.         mklower(fname);                /* msdos/arc isn't case sensitive */
  180. #endif
  181.  
  182.         /*{{{  look for file in an existing buffer*/
  183.         for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
  184.                 if ((bp->b_flag&BFINVS)==0 && strcmp(bp->b_fname, fname)==0) {
  185.                         swbuffer(bp);
  186.                         lp = curwp->w_dotp;
  187.                         i = curwp->w_ntrows/2;
  188.                         while (i-- && lback(lp)!=curbp->b_linep)
  189.                                 lp = lback(lp);
  190.                         curwp->w_linep = lp;
  191.                         curwp->w_flag |= WFMODE|WFHARD;
  192.                         mlwrite(TEXT135);             /*  "[Old buffer]" */
  193.                         return(TRUE);
  194.                 }
  195.         }
  196.         /*}}}*/
  197.  
  198.         makename(bname, fname);                 /* New buffer name.     */
  199.  
  200.         /*{{{  deal with conflicting buffer names*/
  201.         while ((bp=bfind(bname, FALSE, 0)) != NULL) {
  202.                 /* old buffer name conflict code */
  203.                 s = mlreply(TEXT136, bname, NBUFN); /*   "Buffer name: " */
  204.                 if (s == ABORT)                 /* ^G to just quit      */
  205.                         return(s);
  206.                 if (s == FALSE) {               /* CR to clobber it     */
  207.                         makename(bname, fname);
  208.                         break;
  209.                 }
  210.         }
  211.         /*}}}*/
  212.  
  213.         /*{{{  try to make buffer*/
  214.         if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
  215.                 mlwrite(TEXT137);          /*  "Cannot create buffer" */
  216.                 return(FALSE);
  217.         }
  218.         /*}}}*/
  219.  
  220.         if (--curbp->b_nwnd == 0) {             /* Undisplay.           */
  221.                 curbp->b_dotp = curwp->w_dotp;
  222.                 curbp->b_doto = curwp->w_doto;
  223.                 for (cmark = 0; cmark < NMARKS; cmark++) {
  224.                         curbp->b_markp[cmark] = curwp->w_markp[cmark];
  225.                         curbp->b_marko[cmark] = curwp->w_marko[cmark];
  226.                 }
  227.                 curbp->b_fcol = curwp->w_fcol;
  228.         }
  229.         curbp = bp;                             /* Switch to it.        */
  230.         curwp->w_bufp = bp;
  231.         curbp->b_nwnd++;
  232.         return(readin(fname, lockfl));          /* Read it in.          */
  233. }
  234. /*}}}*/
  235.  
  236. /*{{{  PASCAL NEAR indx(s, t)*/
  237. PASCAL NEAR indx(s, t)
  238.  
  239. /*      Index routine, since sun one only works for characters.
  240.  *      Return index of t in s, -1 if none.
  241.  *      MJB: 18-Sep-89.
  242.  */
  243. char s[], t[];
  244. {
  245.         int i, j, k;
  246.  
  247.         for (i = 0; s[i] != '\0'; i++) {
  248.                 for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
  249.                         /* loop */ ;
  250.                 if (t[k] == '\0')
  251.                         return(i);
  252.                 if ((s[i] != '\t') && (s[i] != ' '))
  253.                         return(-1); /* only white space prefix */
  254.         }
  255.         return(-1);
  256. }
  257. /*}}}*/
  258. /*{{{  PASCAL NEAR tindx(s, t, l)*/
  259. PASCAL NEAR tindx(s, t, l)
  260. /*      Index routine, since sun one only works for characters.
  261.  *      Return index of t in s, -1 if none.
  262.  *      This one works with a length for s, a non null terminated string.
  263.  *      MJB: 26-Sep-89.
  264.  */
  265. char s[], t[];
  266. int l;
  267. {
  268.         int i, j, k;
  269.  
  270.         for (i = 0; i <= l; i++) {
  271.                 for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++)
  272.                         /* loop */ ;
  273.                 if (t[k] == '\0')
  274.                         return(i);
  275.                 if ((s[i] != '\t') && (s[i] != ' '))
  276.                         return(-1); /* only white space prefix */
  277.         }
  278.         return(-1);
  279. }
  280. /*}}}*/
  281.         
  282.  
  283. /*{{{  int PASCAL NEAR popmargin(lp)*/
  284. int PASCAL NEAR popmargin(lp)
  285. /*
  286.  * popmargin --   Find the minimum left margin value for the
  287.  *                subsquent lines. Searches back up line in enclosing
  288.  *                open fold. MJB: 20-Oct-89.
  289.  */
  290. LINE    *lp;
  291. {
  292. /*
  293.         while ((lp != curwp->w_bufp->b_linep) &&
  294.                (lp->l_type != LNORMAL)) {
  295.                 if ((lp->l_type == LEOFOLD) ||
  296.                     (lp->l_type == LEOEFOLD))
  297.                         lp = lp->l_foldp;
  298.                 lp = lp->l_bp;
  299.         }
  300.         if (lp->l_type == LNORMAL)
  301.                 return(lp->l_lmargin);
  302.         else
  303.                 return(0);
  304. */
  305.         /* MJB 27-Feb-90 */
  306.         /* isn't this what we need! */
  307.         if ((lp->l_type == LEOFOLD) ||
  308.             (lp->l_type == LEOEFOLD)) 
  309.                 lp = lp->l_foldp;
  310.         return(lp->l_lmargin);
  311. }
  312. /*}}}*/
  313.  
  314. /*{{{  PASCAL NEAR readin(fname, lockfl)*/
  315. PASCAL NEAR readin(fname, lockfl)
  316.  
  317. /*
  318.         Read file "fname" into the current buffer, blowing away any text
  319.         found there.  Called by both the read and find commands.  Return
  320.         the final status of the read.  Also called by the mainline, to
  321.         read in a file specified on the command line as an argument. 
  322.         The command in $readhook is called after the buffer is set up
  323.         and before it is read. 
  324.  
  325.         Folding requirements: The file type is identified and stored
  326.                               in the buffer. MJB 13-Sep-89.
  327. */
  328.  
  329.  
  330. char    fname[];        /* name of file to read */
  331. int     lockfl;         /* check for file locks? */
  332.  
  333. {
  334.         /*{{{  declare vars*/
  335.         register LINE *lp1;
  336.         register LINE *lp2;
  337.         register int i;
  338.         register WINDOW *wp;
  339.         register BUFFER *bp;
  340.         register int s;
  341.         register int nbytes;
  342.         register int nline;
  343.         register int cmark;     /* current mark */
  344.         char mesg[NSTRING];
  345.         register int pidx;
  346.         register FOLDMARKENT *tp;
  347.         char str[NSTRING];
  348.         int lmargin;
  349.         /*}}}*/
  350.  
  351.  
  352. #if     FILOCK
  353.         if (lockfl && lockchk(fname) == ABORT)
  354.                 return(ABORT);
  355. #endif
  356.  
  357.         /*{{{  prepare the buffer*/
  358.         bp = curbp;                             /* Cheap.               */
  359.         mlwrite("[Tidying]");
  360.         if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  361.                 return(s);
  362.         bp->b_flag &= ~(BFINVS|BFCHG);
  363.         
  364.         strcpy(bp->b_fname, fname);
  365.         /*}}}*/
  366.  
  367.         /*{{{  find file type*/
  368.         if (getftype(fname, bp->b_ftype))   /* dd: MAY-91        */
  369.         { 
  370.           tp = setfolds(bp->b_ftype);
  371.           strcpy(mesg,"[file type ");
  372.           strcat(mesg,bp->b_ftype);
  373.           strcat(mesg,"]");
  374.           mlwrite(mesg);
  375.         }
  376.         else tp = NULL;
  377.         /*}}}*/
  378.  
  379.         /*{{{  call user's read-hook*/
  380.         /* let a user macro get hold of things...if he wants */
  381.         execkey(&readhook, FALSE, 1);
  382.         /*}}}*/
  383.  
  384. #if     CRYPT
  385.         /*{{{  prepare to decrypt*/
  386.         /* set up for decryption */
  387.         s = resetkey();
  388.         if (s != TRUE)
  389.                 return(s);
  390.         /*}}}*/
  391. #endif
  392.  
  393.         /*{{{  turn off kybd translation*/
  394.         /* turn off ALL keyboard translation in case we get a dos error */
  395.         TTkclose();
  396.         /*}}}*/
  397.  
  398.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  399.                 goto out;
  400.  
  401.         if (s == FIOFNF) {                      /* File not found.      */
  402.                 mlwrite(TEXT138);               /* "[New file]" */
  403.                 goto out;
  404.         }
  405.  
  406.         /* read the file in */
  407. #if 1 
  408.        mlwrite(TEXT139);        /*     "[Reading file]" */
  409. #endif
  410.         nline = 0;
  411.         lmargin = 0;
  412.  
  413.         while ((s=ffgetline()) == FIOSUC) {
  414.                 /* Allow for a file with blank lines - ned? */
  415.                 nbytes = (strlen(fline) > lmargin) ? strlen(fline) : lmargin;
  416.                 if ((lp1=lalloc(nbytes)) == NULL) {
  417.                         s = FIOMEM;             /* Keep message on the  */
  418.                         break;                  /* display.             */
  419.                 }
  420.  
  421.                 /* If it was blank, we had better initialise it! */
  422.                 if (strlen(fline) < lmargin) 
  423.                         for (i = strlen(fline); i < lmargin; i++)
  424.                                 fline[i] = ' ';
  425.  
  426.                 lp2 = curbp->b_linep->l_bp;
  427.                 lp2->l_fp = lp1;
  428.                 lp1->l_fp = curbp->b_linep;
  429.                 lp1->l_bp = lp2;
  430.                 curbp->b_linep->l_bp = lp1;
  431.  
  432.                 /* check for fold lines. MJB: 15-Sep-89 */
  433.                 if ((tp != (FOLDMARKENT *)NULL) && 
  434.                     (pidx = indx(fline, tp->fm_startopen)) != -1)
  435.  
  436.                   /*{{{  start of fold symbol*/
  437.                   {
  438.                           /* offset */
  439.                           strncpy(str, fline, pidx);
  440.                           str[pidx] = '\0';                       
  441.                           /* fold symbol */
  442.                           strcat(str, FOLDSYMBOL);
  443.                           /* comment */
  444.                           strcat(str, &fline[pidx + strlen(tp->fm_startopen)]);
  445.                           /* make sure string is long enough to remove close */
  446.                           if ((strlen(str) - pidx - strlen(FOLDSYMBOL))
  447.                                >= strlen(tp->fm_startclose))
  448.                                   str[strlen(str) - strlen(tp->fm_startclose)] = '\0';
  449.                           /* back to fline, and adjust byte count */
  450.                           strcpy(fline, str);
  451.                           nbytes = strlen(fline);
  452.                           lp1->l_used = nbytes;
  453.                           /* set line type, and record start of fold */
  454.                           lp1->l_type = LSOFOLD;
  455.                           lp1->l_lmargin = lmargin;
  456.                           lmargin = pidx;
  457.                           pushline(lp1);
  458.                   }
  459.                   /*}}}*/
  460.  
  461.                 else if ((tp != (FOLDMARKENT *)NULL) &&
  462.                          (pidx = indx(fline, tp->fm_end)) != -1)
  463.  
  464.                   /*{{{  end of fold symbol*/
  465.                   {
  466.                           if (linelist->fll_bp->fll_line != (LINE *)NULL) {
  467.                                   /* offset */
  468.                                   strncpy(str, fline, pidx);
  469.                                   str[pidx] = '\0';                       
  470.                                   /* fold symbol */
  471.                                   strcat(str, ENDFOLD);
  472.                                   /* end fold comment from ned or the like! */
  473.                                   strcat(str, &fline[pidx + strlen(tp->fm_end)]);
  474.                                   /* back to fline, and adjust byte count */
  475.                                   strcpy(fline, str);
  476.                                   nbytes = strlen(fline);
  477.                                   lp1->l_used = nbytes;
  478.                                   /* set line type, and record start of fold */
  479.                                   lp1->l_type = LEOFOLD;
  480.                                   lp1->l_foldp = popline();
  481.                                   lp1->l_foldp->l_foldp = lp1;
  482.                                   lmargin = popmargin(lp1); /* recalculation */
  483.                                   lp1->l_lmargin = lmargin;
  484.                           }
  485.                           else { /* Just to be safe! */
  486.                           lp1->l_type = LNORMAL;
  487.                                   lp1->l_foldp = (LINE *)NULL;
  488.                                   mlwrite(TEXT231); /* "Missing start-fold Marker */
  489.                           }
  490.                   }
  491.                   /*}}}*/
  492.  
  493.                 else {
  494.                         lp1->l_type = LNORMAL;
  495.                         lp1->l_foldp = (LINE *)NULL;
  496.                         lp1->l_lmargin = lmargin;
  497.                 }
  498.                 for (i=0; i<nbytes; ++i)
  499.                         lputc(lp1, i, fline[i]);
  500.                 ++nline;
  501.         }
  502.         ffclose();                              /* Ignore errors.       */
  503.         strcpy(mesg, "[");
  504.         if (s==FIOERR) {
  505.                 strcat(mesg, TEXT141);
  506. /*                           "I/O ERROR, " */
  507.                 curbp->b_flag |= BFTRUNC;
  508.         }
  509.         if (s == FIOMEM) {
  510.                 strcat(mesg, TEXT142);
  511. /*                           "OUT OF MEMORY, " */
  512.                 curbp->b_flag |= BFTRUNC;
  513.         }
  514.         /* check to see if matching number of start/end fold markers */
  515.         /* if not try to tidy up a bit. MJB: 22-Sep-89 */
  516.         while (linelist->fll_bp->fll_line != (LINE *)NULL) {
  517.                 lp1 = popline();
  518.                 lp1->l_type = LNORMAL;
  519.                 mlwrite(TEXT230);
  520. /*                      "Missing end-fold Marker " */
  521.                 s = FIOERR;
  522.         }
  523.  
  524.         /*{{{  show no lines read*/
  525.         strcat(mesg, TEXT140);       /*   "Read " */
  526.         strcat(mesg, int_asc(nline));
  527.         strcat(mesg, TEXT143);       /*  " line" */
  528.         if (nline > 1)
  529.                 strcat(mesg, "s");
  530.         strcat(mesg, "]");
  531.         mlwrite(mesg);
  532.         /*}}}*/
  533.  
  534. out:
  535.         TTkopen();      /* open the keyboard again */
  536.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  537.                 if (wp->w_bufp == curbp) {
  538.                         wp->w_linep = lforw(curbp->b_linep);
  539.                         wp->w_dotp  = lforw(curbp->b_linep);
  540.                         wp->w_doto  = 0;
  541.                         for (cmark = 0; cmark < NMARKS; cmark++) {
  542.                                 wp->w_markp[cmark] = NULL;
  543.                                 wp->w_marko[cmark] = 0;
  544.                         }
  545.                         wp->w_flag |= WFMODE|WFHARD;
  546.                 }
  547.         }
  548.         if (s == FIOERR || s == FIOFNF)         /* False if error.      */
  549.                 return(FALSE);
  550.         return(TRUE);
  551. }
  552. /*}}}*/
  553.  
  554. /*{{{  char *PASCAL NEAR makename(bname, fname)*/
  555. char *PASCAL NEAR makename(bname, fname)
  556. /*
  557.  * Take a file name, and from it
  558.  * fabricate a buffer name. This routine knows
  559.  * about the syntax of file names on the target system.
  560.  * I suppose that this information could be put in
  561.  * a better place than a line of code.
  562.  * Returns a pointer into fname indicating the end of the file path; i.e.,
  563.  * 1 character BEYOND the path name.
  564.  */
  565. char    bname[];
  566. char    fname[];
  567. {
  568.         register char *cp1;
  569.         register char *cp2;
  570.         register char *pathp;
  571.  
  572. #if     AOSVS | MV_UX
  573.         resolve_full_pathname(fname, fname);
  574.         mklower(fname);   /* aos/vs not case sensitive */
  575. #endif
  576.         cp1 = &fname[0];
  577.         while (*cp1 != 0)
  578.                 ++cp1;
  579.  
  580. #if     AMIGA
  581.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
  582.                 --cp1;
  583. #endif
  584. #if     AOSVS | MV_UX
  585.         while (cp1!=&fname[0] && cp1[-1]!=':')
  586.                 --cp1;
  587. #endif
  588. #if     VMS
  589.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
  590.                 --cp1;
  591. #endif
  592. #if     MSDOS | MSDOS
  593.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  594.                 --cp1;
  595. #endif
  596. #if     ST520
  597.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
  598.                 --cp1;
  599. #endif
  600. #if     FINDER
  601.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  602.                 --cp1;
  603. #endif
  604. #if     V7 | USG | HPUX | BSD | SUN | XENIX
  605.         while (cp1!=&fname[0] && cp1[-1]!='/')
  606.                 --cp1;
  607. #endif
  608. #if WMCS
  609.         while (cp1!=&fname[0] && cp1[-1]!='_' && cp1[-1]!='/')
  610.                 --cp1;
  611. #endif
  612. #if     RISCOS
  613.         while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='.')
  614.                 --cp1;
  615. #endif
  616.         /* cp1 is pointing to the first real filename char */
  617.         pathp = cp1;
  618.  
  619.         cp2 = &bname[0];
  620.         while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
  621.                 *cp2++ = *cp1++;
  622.         *cp2 = 0;
  623.  
  624.         return(pathp);
  625. }
  626. /*}}}*/
  627.  
  628. /*{{{  FOLDMARKENT *PASCAL NEAR setfolds(ftype)*/
  629. FOLDMARKENT *PASCAL NEAR setfolds(ftype)
  630. /*
  631.  * set fold markers according to file type
  632.  */
  633. char    *ftype;
  634. {
  635.         /*{{{  declare vars*/
  636.         register FOLDMARKENT *tp,*catchall;
  637.         
  638.         
  639.         
  640.         
  641.         /*}}}*/
  642.  
  643.         /* compare ftype with all the extensions in the table */
  644.  
  645.         tp = foldmarktab;
  646.         catchall = NULL;
  647.         while (tp != NULL) {
  648.                 if (strcmp("*", tp->fm_extension) == 0)
  649.                         catchall = tp;
  650.                         
  651.                 if (strcmp(ftype, tp->fm_extension) == 0)
  652.                         return(tp);
  653.                 else 
  654.                         tp = tp->fm_next;
  655.         }
  656.         return(catchall);
  657. }
  658. /*}}}*/
  659.  
  660. #if RISCOS
  661. /*{{{  int PASCAL NEAR knowntype(ftype)*/
  662. int PASCAL NEAR knowntype(ftype)
  663. /*
  664.  * see if ftype is known
  665.  */
  666. char    *ftype;
  667. {
  668.  
  669.  
  670.         /* compare ftype with all the extensions in the table */
  671.  
  672.         register FOLDMARKENT *tp = foldmarktab;
  673.         
  674.         while (tp != NULL) {
  675.                 if (strcmp("*", tp->fm_extension) == 0)
  676.                      return(1);
  677.                         
  678.                 if (strcmp(ftype, tp->fm_extension) == 0)
  679.                         return(1);
  680.                 else 
  681.                         tp = tp->fm_next;
  682.         }
  683.         return(0);
  684. }
  685. /*}}}*/
  686. #endif
  687.  
  688. /*{{{  int PASCAL NEAR getftype(fname,ftype)*/
  689. int PASCAL NEAR getftype(fname,ftype)
  690. /*
  691.  * Take a file name, and from it identify the file type.
  692.  * MJB: 13-Sep-89.
  693.  * div - riscos vsn, tries to get riscos file type, if there is no sign
  694.          of an extension at start or end
  695.          returns pointer to fold marker set, and also copies textual type
  696.          to ftype buffer
  697.  
  698.  * used to also set the fold markers, but no longer...
  699.  */
  700. char    *fname;
  701. char    *ftype;
  702.  
  703. #if RISCOS
  704.  
  705.   /*{{{  riscos vsn*/
  706.   {
  707.           /*{{{  declare vars*/
  708.           _kernel_osfile_block block;
  709.           register char *cp1, *cp2 = ftype;
  710.           
  711.           *ftype = 0;
  712.           /*}}}*/
  713.   
  714.           /*{{{  look for form path.c.filename*/
  715.           if (cp1 = strrchr(fname,'.'))
  716.           
  717.           { 
  718.              /*{{{  find next-last dot, or start of fname*/
  719.              for (--cp1; (cp1 > fname) && (*cp1 != '.'); --cp1);
  720.              
  721.              if (*cp1=='.') ++cp1;
  722.              /*}}}*/
  723.           
  724.              
  725.              for (cp2=ftype; *cp1 != '.';)
  726.                 if (!(*cp2++ = *cp1++))
  727.                     return(0);              /* something went wrong - expected a . */
  728.                     
  729.              *cp2 = 0;
  730.           
  731.              if (knowntype(ftype))           /* if recognised the file type */
  732.                   return(1);
  733.           }        
  734.           /*}}}*/
  735.   
  736.           /*{{{  look for recognized type after a _*/
  737.           if ((cp1 = strrchr(fname,'_')) && knowntype(cp1+1))
  738.           
  739.           {  strcpy(ftype,cp1+1);
  740.              return(1);
  741.           }
  742.           
  743.           /*}}}*/
  744.     
  745.           /*{{{  try to get file type, though its usually Text !*/
  746.           
  747.           if
  748.              /*{{{  its a file with a type stamp*/
  749.              ((_kernel_osfile(17, fname, &block)==1)    &&
  750.               ((block.load & 0xfff00000) == 0xfff00000))
  751.              /*}}}*/
  752.           
  753.                /*{{{  translate it to a name in ftype and return*/
  754.                {  _kernel_swi_regs regs;
  755.                
  756.                   regs.r[0] = 18;
  757.                   regs.r[2] = (block.load >> 8) & 0xfff;   /* file type */
  758.                
  759.                   _kernel_swi(0x29, ®s, ®s);   /* os_fscontrol 18 */
  760.                
  761.                   for (cp1 = (char *) (®s.r[2]), cp2=ftype;
  762.                        (cp2 < ftype+8) && (*cp1 != ' ');
  763.                        *cp2++ = *cp1++);
  764.                   *cp2=0;
  765.                
  766.                   if (knowntype(ftype))
  767.                     return(1);
  768.                
  769.                }
  770.                /*}}}*/
  771.           /*}}}*/
  772.         
  773.           return(0); /* failed */
  774.   
  775.   }
  776.   /*}}}*/
  777.  
  778. #else
  779.  
  780.   /*{{{  original-ish vsn*/
  781.   {
  782.           register char *cp1;
  783.   
  784.   
  785.   #  if   AOSVS | MV_UX
  786.           resolve_full_pathname(fname, fname);
  787.           mklower(fname);   /* aos/vs not case sensitive */
  788.   #  endif
  789.   
  790.           cp1 = &fname[0];
  791.           while (*cp1 != 0)
  792.                   ++cp1;
  793.   
  794.           while (cp1!=&fname[0] && cp1[-1]!='.')
  795.                   --cp1;
  796.   
  797.           if (cp1 = fname)
  798.                return(*ftype=0);  /* no extension */
  799.    
  800.           /* cp1 is pointing to the first character of extention  */
  801.   
  802.           strcpy(ftype, cp1);
  803.            
  804.           return(1);
  805.   }
  806.   /*}}}*/
  807.  
  808. #endif
  809. /*}}}*/
  810.  
  811. /*{{{  PASCAL NEAR unqname(name)       - make sure a buffer name is unique*/
  812. PASCAL NEAR unqname(name)       /* make sure a buffer name is unique */
  813.  
  814. char *name;     /* name to check on */
  815.  
  816. {
  817.         register char *sp;
  818.  
  819.         /* check to see if it is in the buffer list */
  820.         while (bfind(name, 0, FALSE) != NULL) {
  821.  
  822.                 /* go to the end of the name */
  823.                 sp = name;
  824.                 while (*sp)
  825.                         ++sp;
  826.                 if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) {
  827.                         *sp++ = '0';
  828.                         *sp = 0;
  829.                 } else
  830.                       *(--sp) += 1;
  831.         }
  832. }
  833. /*}}}*/
  834.  
  835. /*{{{  PASCAL NEAR filewrite(f, n)*/
  836. PASCAL NEAR filewrite(f, n)
  837. /*
  838.  * Ask for a file name, and write the
  839.  * contents of the current buffer to that file.
  840.  * Update the remembered file name and clear the
  841.  * buffer changed flag. This handling of file names
  842.  * is different from the earlier versions, and
  843.  * is more compatable with Gosling EMACS than
  844.  * with ITS EMACS. Bound to "C-X C-W".
  845.  */
  846. {
  847.         register int s;
  848.         char fname[NFILEN];
  849.  
  850.         if (restflag)           /* don't allow this command if restricted */
  851.                 return(resterr());
  852.         if ((s=mlreply(TEXT144, fname, NFILEN)) != TRUE)
  853. /*                     "Write file: " */
  854.                 return(s);
  855.         if ((s=writeout(fname)) == TRUE) {
  856.                 strcpy(curbp->b_fname, fname);
  857.                 curbp->b_flag &= ~BFCHG;
  858.                 /* Update mode lines.   */
  859.                 upmode();
  860.         }
  861.         return(s);
  862. }
  863. /*}}}*/
  864.  
  865. /*{{{  PASCAL NEAR filesave(f, n)*/
  866. PASCAL NEAR filesave(f, n)
  867. /*
  868.  * Save the contents of the current
  869.  * buffer in its associatd file. Do nothing
  870.  * if nothing has changed (this may be a bug, not a
  871.  * feature). Error if there is no remembered file
  872.  * name for the buffer. Bound to "C-X C-S". May
  873.  * get called by "C-Z".
  874.  */
  875. {
  876.         register int s;
  877.  
  878.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  879.                 return(rdonly());       /* we are in read only mode     */
  880.         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  881.                 return(TRUE);
  882.         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  883.                 mlwrite(TEXT145);
  884. /*                      "No file name" */
  885.                 return(FALSE);
  886.         }
  887.  
  888.         /* complain about truncated files */
  889.         if ((curbp->b_flag&BFTRUNC) != 0) {
  890.                 if (mlyesno(TEXT146) == FALSE) {
  891. /*                          "Truncated file..write it out" */
  892.                         mlwrite(TEXT8);
  893. /*                              "[Aborted]" */
  894.                         return(FALSE);
  895.                 }
  896.         }
  897.  
  898.         /* complain about narrowed buffers */
  899.         if ((curbp->b_flag&BFNAROW) != 0) {
  900.                 if (mlyesno(TEXT147) == FALSE) {
  901. /*                          "Narrowed Buffer..write it out" */
  902.                         mlwrite(TEXT8);
  903. /*                              "[Aborted]" */
  904.                         return(FALSE);
  905.                 }
  906.         }
  907.  
  908.         if ((s=writeout(curbp->b_fname)) == TRUE) {
  909.                 curbp->b_flag &= ~BFCHG;
  910.                 /* Update mode lines.   */
  911.                 upmode();
  912.         }
  913.         return(s);
  914. }
  915. /*}}}*/
  916.  
  917. /*{{{  int PASCAL NEAR fileisfolded()*/
  918. int PASCAL NEAR fileisfolded()
  919. /* fileisfolded: check to see if a file contains folds
  920. */
  921.  
  922. {
  923.    register LINE *lp = curbp->b_linep->l_fp; /* first line */
  924.  
  925.    while (lp != curbp->b_linep) {
  926.       if (lp->l_type != LNORMAL)
  927.          return TRUE;
  928.  
  929.       lp = lp->l_fp;    /* next line */
  930.    }
  931.  
  932.    return FALSE;
  933. }
  934. /*}}}*/
  935.  
  936. /*{{{  PASCAL NEAR writeout(fn)*/
  937. PASCAL NEAR writeout(fn)
  938. /*
  939.  * This function performs the details of file writing. It uses
  940.  * the file management routines in the "fileio.c" package. The
  941.  * number of lines written is displayed. Several errors are
  942.  * posible, and cause writeout to return a FALSE result. When
  943.  * $ssave is TRUE,  the buffer is written out to a temporary
  944.  * file, and then the old file is unlinked and the temporary
  945.  * renamed to the original name.  Before the file is written,
  946.  * a user specifyable routine (in $writehook) can be run.
  947.  */
  948.  
  949.  
  950. char *fn;       /* name of file to write current buffer to */
  951.  
  952. {
  953.         register LINE *lp;      /* line to scan while writing */
  954.         register char *sp;      /* temporary string pointer */
  955.         register int nline;     /* number of lines written */
  956.         int status;             /* return status */
  957.         int sflag;              /* are we safe saving? */
  958.         char tname[NSTRING];    /* temporary file name */
  959. #if RISCOS
  960.         char ttype[NTYPEN];    /* temporary file type */
  961. #endif
  962.         char buf[NSTRING];      /* message buffer */
  963.         register int pidx;
  964.         register FOLDMARKENT *tp;
  965.         char str[NSTRING];
  966.  
  967.         /* let a user macro get hold of things...if he wants */
  968.         execkey(&writehook, FALSE, 1);
  969.         
  970.         /* Exit from any entered folds. MJB: 22-Sep-89. */
  971.         exitallfolds();
  972.  
  973.         /* Set foldmarker table pointer for this file type. MJB: 18-Sep-89 */
  974.         tp = setfolds(curbp->b_ftype);     /* BG: 11-Oct-89; dd may-91 */
  975.         if (tp == NULL) 
  976.            if (fileisfolded() == TRUE) {
  977.               mlwrite(TEXT237);
  978.               return(FIODEL);        /* Fail, no fold marks set */
  979.            }
  980.  
  981.         /* determine if we will use the save method */
  982.         sflag = FALSE;
  983.         if (ssave && fexist(fn))
  984.                 sflag = TRUE;
  985.  
  986. #if     CRYPT
  987.         /* set up for file encryption */
  988.         status = resetkey();
  989.         if (status != TRUE)
  990.                 return(status);
  991. #endif
  992.  
  993.         /* turn off ALL keyboard translation in case we get a dos error */
  994.         TTkclose();
  995.  
  996.         /* Perform Safe Save..... */
  997.         if (sflag) {
  998.                 /* duplicate original file name, and find where to trunc it */
  999.                 sp = tname + (makename(tname, fn) - fn) + 1;
  1000.                 strcpy(tname, fn);
  1001.  
  1002.                 /* create a unique name, using random numbers */
  1003.                 do {
  1004.                         *sp = 0;
  1005.                         strcat(tname, int_asc(ernd()));
  1006.                 } while(fexist(tname));
  1007.  
  1008.                 /* open the temporary file */
  1009. #if     AOSVS
  1010.                 status = ffwopen(fn, tname);
  1011. #else
  1012.                 status = ffwopen(tname);
  1013. #endif
  1014.         } else
  1015. #if     AOSVS
  1016.                 status = ffwopen(fn, NULL);
  1017. #else
  1018.                 status = ffwopen(fn);
  1019. #endif
  1020.  
  1021.         /* if the open failed.. clean up and abort */
  1022.         if (status != FIOSUC) {
  1023.                 TTkopen();
  1024.                 return(FALSE);
  1025.         }
  1026.  
  1027.         /* write the current buffer's lines to the open disk file */
  1028.         mlwrite(TEXT148);       /* tell us that we're writing */
  1029. /*              "[Writing...]" */
  1030.  
  1031. /*      Check to see if lines are open folds, and if so substitute the 
  1032.  *      markers for the fold symbol. MJB: 18-Sep-89.
  1033.  */
  1034.  
  1035.         lp = curbp->b_linep->l_fp;      /* start at the first line.     */
  1036.         nline = 0;                      /* track the Number of lines    */
  1037.         while (lp != curbp->b_linep) {
  1038.                 if (lp->l_type == LSOFOLD) {
  1039.                         if ((pidx = indx(lp->l_text, FOLDSYMBOL)) != -1) {
  1040.                                 /* indentation */
  1041.                                 strncpy(str, lp->l_text, pidx);
  1042.                                 str[pidx] = '\0';                       
  1043.                                 /* fold symbol */
  1044.                                 strcat(str, tp->fm_startopen);
  1045.                                 /* comment */
  1046.                                 if (pidx + strlen(FOLDSYMBOL) < llength(lp))
  1047.                                         strncat(str, 
  1048.                                                 &lp->l_text[pidx + strlen(FOLDSYMBOL)],
  1049.                                                 (llength(lp) - strlen(FOLDSYMBOL) - pidx));
  1050.                                 strcat(str, tp->fm_startclose);
  1051.                                 if ((status = ffputline(&str[0], strlen(str)))
  1052.                                               != FIOSUC)
  1053.                                         break;
  1054.                         }
  1055.                         else
  1056.                         if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  1057.                                 break;
  1058.                 }
  1059.                 else if (lp->l_type == LSOEFOLD) {
  1060.                         if ((pidx = indx(lp->l_text, BEGINFOLD)) != -1) {
  1061.                                 /* indentation */
  1062.                                 strncpy(str, lp->l_text, pidx);
  1063.                                 str[pidx] = '\0';                       
  1064.                                 /* fold symbol */
  1065.                                 strcat(str, tp->fm_startopen);
  1066.                                 /* comment */
  1067.                                 if (pidx + strlen(BEGINFOLD) < llength(lp))
  1068.                                         strncat(str, 
  1069.                                                 &lp->l_text[pidx + strlen(FOLDSYMBOL)],
  1070.                                                 (llength(lp) - strlen(FOLDSYMBOL) - pidx));
  1071.                                 strcat(str, tp->fm_startclose);
  1072.                                 if ((status = ffputline(&str[0], strlen(str)))
  1073.                                               != FIOSUC)
  1074.                                         break;
  1075.                         }
  1076.                         else
  1077.                         if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  1078.                                 break;
  1079.                 }
  1080.                 else if ((lp->l_type == LEOFOLD) || (lp->l_type == LEOEFOLD)) {
  1081.                         if ((pidx = indx(lp->l_text, ENDFOLD)) != -1) {
  1082.                                 /* indentation */
  1083.                                 strncpy(str, lp->l_text, pidx);
  1084.                                 str[pidx] = '\0';                       
  1085.                                 /* fold symbol */
  1086.                                 strcat(str, tp->fm_end);
  1087.                                 /* trailer - from ned or the like! */
  1088.                                 if (pidx + strlen(ENDFOLD) < llength(lp))
  1089.                                         strncat(str, &lp->l_text[pidx + strlen(FOLDSYMBOL)],
  1090.                                                 llength(lp) - strlen(ENDFOLD) - pidx);
  1091.                                 if ((status = ffputline(&str[0], strlen(str)))
  1092.                                               != FIOSUC)
  1093.                                         break;
  1094.                         }
  1095.                         else
  1096.                         if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  1097.                                 break;
  1098.                 }
  1099.                 else if ((status = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  1100.                         break;
  1101.                 ++nline;
  1102.                 lp = lp->l_fp;
  1103.         }
  1104.  
  1105.  
  1106.         /* report on status of file write */
  1107.         *buf = 0;
  1108.         status |= ffclose();
  1109.         if (status == FIOSUC) {
  1110.                 /* report on success (or lack therof) */
  1111.                 strcpy(buf, TEXT149);
  1112. /*                          "[Wrote " */
  1113.                 strcat(buf, int_asc(nline));
  1114.                 strcat(buf, TEXT143);
  1115. /*                          " line" */
  1116.                 if (nline > 1)
  1117.                         strcat(buf, "s");
  1118.  
  1119.                 if (sflag) {
  1120.                         /* erase original file */
  1121.                         /* rename temporary file to original name */
  1122.                         if (unlink(fn) == 0 && rename(tname, fn) == 0)
  1123.                                 ;
  1124.                         else {
  1125.                                 strcat(buf, TEXT150);
  1126. /*                                          ", saved as " */
  1127.                                 strcat(buf, tname);
  1128.                                 status = FIODEL;            /* failed */
  1129.                         }
  1130.                 }
  1131.                 strcat(buf, "]");
  1132.                 mlwrite(buf);
  1133.         }
  1134.  
  1135.         /* reopen the keyboard, and return our status */
  1136.         TTkopen();
  1137.         return(status == FIOSUC);
  1138. }
  1139. /*}}}*/
  1140.  
  1141. /*{{{  PASCAL NEAR filename(f, n)*/
  1142. PASCAL NEAR filename(f, n)
  1143. /*
  1144.  * The command allows the user
  1145.  * to modify the file name associated with
  1146.  * the current buffer. It is like the "f" command
  1147.  * in UNIX "ed". The operation is simple; just zap
  1148.  * the name in the BUFFER structure, and mark the windows
  1149.  * as needing an update. You can type a blank line at the
  1150.  * prompt if you wish.
  1151.  */
  1152.  
  1153.  
  1154. {
  1155.         register int    s;
  1156.         char            fname[NFILEN];
  1157.  
  1158.         if (restflag)           /* don't allow this command if restricted */
  1159.                 return(resterr());
  1160.         if ((s=mlreply(TEXT151, fname, NFILEN)) == ABORT)
  1161. /*                     "Name: " */
  1162.                 return(s);
  1163.         if (s == FALSE)
  1164.                 strcpy(curbp->b_fname, "");
  1165.         else
  1166.                 strcpy(curbp->b_fname, fname);
  1167.         /* Update mode lines.   */
  1168.         upmode();
  1169.         curbp->b_mode &= ~MDVIEW;      /* no longer read only mode */
  1170.         return(TRUE);
  1171. }
  1172. /*}}}*/
  1173.  
  1174. /*{{{  PASCAL NEAR ifile(fname)*/
  1175. PASCAL NEAR ifile(fname)
  1176. /*
  1177.  * Insert file "fname" into the current
  1178.  * buffer, Called by insert file command. Return the final
  1179.  * status of the read.
  1180.  */
  1181. char    fname[];
  1182. {
  1183.         register LINE *lp0;
  1184.         register LINE *lp1;
  1185.         register LINE *lp2;
  1186.         register int i;
  1187.         register BUFFER *bp;
  1188.         register int s;
  1189.         register int nbytes;
  1190.         register int nline;
  1191.         int cmark;      /* current mark */
  1192.         char mesg[NSTRING];
  1193.         char str[NSTRING];
  1194.         register int pidx;
  1195.         register int lmargin;
  1196.         register FOLDMARKENT *tp;
  1197.         char ftype[NTYPEN];
  1198.  
  1199.         bp = curbp;                             /* Cheap.               */
  1200.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  1201.                 goto out;
  1202.         if (s == FIOFNF) {                      /* File not found.      */
  1203.                 mlwrite(TEXT152);
  1204. /*                      "[No such file]" */
  1205.                 return(FALSE);
  1206.         }
  1207.         mlwrite(TEXT153);
  1208. /*              "[Inserting file]" */
  1209.  
  1210. #if     CRYPT
  1211.         s = resetkey();
  1212.         if (s != TRUE)
  1213.                 return(s);
  1214. #endif
  1215.         if (getftype(fname, ftype))
  1216.           tp = setfolds(ftype);
  1217.           
  1218.         lmargin = 0;
  1219.  
  1220.         /* back up a line and save the mark here */
  1221.         curwp->w_dotp = curwp->w_dotp->l_bp;
  1222.         curwp->w_doto = 0;
  1223.         for (cmark = 0; cmark < NMARKS; cmark++) {
  1224.                 curwp->w_markp[cmark] = curwp->w_dotp;
  1225.                 curwp->w_marko[cmark] = 0;
  1226.         }
  1227.  
  1228.         nline = 0;
  1229.         while ((s=ffgetline()) == FIOSUC) {
  1230.                 nbytes = strlen(fline);
  1231.                 if ((lp1=lalloc(nbytes)) == NULL) {
  1232.                         s = FIOMEM;             /* Keep message on the  */
  1233.                         break;                  /* display.             */
  1234.                 }
  1235.  
  1236.                 if ((tp != (FOLDMARKENT *)NULL) && 
  1237.                     (pidx = indx(fline, tp->fm_startopen)) != -1) {
  1238.                         /* offset */
  1239.                         strncpy(str, fline, pidx);
  1240.                         str[pidx] = '\0';                       
  1241.                         /* fold symbol */
  1242.                         strcat(str, FOLDSYMBOL);
  1243.                         /* comment */
  1244.                         strcat(str, &fline[pidx + strlen(tp->fm_startopen)]);
  1245.                         /* make sure string is long enough to remove close */
  1246.                         if ((strlen(str) - pidx - strlen(FOLDSYMBOL))
  1247.                              >= strlen(tp->fm_startclose))
  1248.                                 str[strlen(str) - strlen(tp->fm_startclose)] = '\0';
  1249.                         /* back to fline, and adjust byte count */
  1250.                         strcpy(fline, str);
  1251.                         nbytes = strlen(fline);
  1252.                         lp1->l_used = nbytes;
  1253.                         /* set line type, and record start of fold */
  1254.                         lp1->l_type = LSOFOLD;
  1255.                         lp1->l_lmargin = lmargin;
  1256.                         lmargin = pidx;
  1257.                         pushline(lp1);
  1258.                 }
  1259.                 else if ((tp != (FOLDMARKENT *)NULL) &&
  1260.                          (pidx = indx(fline, tp->fm_end)) != -1) {
  1261.                         if (linelist->fll_bp->fll_line != (LINE *)NULL) {
  1262.                                 /* offset */
  1263.                                 strncpy(str, fline, pidx);
  1264.                                 str[pidx] = '\0';                       
  1265.                                 /* fold symbol */
  1266.                                 strcat(str, ENDFOLD);
  1267.                                 /* back to fline, and adjust byte count */
  1268.                                 strcpy(fline, str);
  1269.                                 nbytes = strlen(fline);
  1270.                                 lp1->l_used = nbytes;
  1271.                                 /* set line type, and record start of fold */
  1272.                                 lp1->l_type = LEOFOLD;
  1273.                                 lp1->l_foldp = popline();
  1274.                                 lp1->l_foldp->l_foldp = lp1;
  1275.                                 lmargin = popmargin(lp1); /* recalculation */
  1276.                                 lp1->l_lmargin = lmargin;
  1277.                         }
  1278.                         else { /* Just to be safe! */
  1279.                         lp1->l_type = LNORMAL;
  1280.                                 lp1->l_foldp = (LINE *)NULL;
  1281.                                 mlwrite(TEXT231);
  1282. /*                                      "Missing start-fold Marker */
  1283.                         }
  1284.                 }
  1285.                 else {
  1286.                         lp1->l_type = LNORMAL;
  1287.                         lp1->l_foldp = (LINE *)NULL;
  1288.                         lp1->l_lmargin = lmargin;
  1289.                 }
  1290.  
  1291.                 lp0 = curwp->w_dotp;  /* line previous to insert */
  1292.                 lp2 = lp0->l_fp;        /* line after insert */
  1293.  
  1294.                 /* re-link new line between lp0 and lp2 */
  1295.                 lp2->l_bp = lp1;
  1296.                 lp0->l_fp = lp1;
  1297.                 lp1->l_bp = lp0;
  1298.                 lp1->l_fp = lp2;
  1299.  
  1300.                 /* and advance and write out the current line */
  1301.                 curwp->w_dotp = lp1;
  1302.                 for (i=0; i<nbytes; ++i)
  1303.                         lputc(lp1, i, fline[i]);
  1304.                 ++nline;
  1305.         }
  1306.  
  1307.         ffclose();                              /* Ignore errors.       */
  1308.         curwp->w_markp[0] = lforw(curwp->w_markp[0]);
  1309.         strcpy(mesg, "[");
  1310.  
  1311.         if (s==FIOERR) {
  1312.                 strcat(mesg, TEXT141);
  1313. /*                           "I/O ERROR, " */
  1314.                 curbp->b_flag |= BFTRUNC;
  1315.         }
  1316.         if (s == FIOMEM) {
  1317.                 strcat(mesg, TEXT142);
  1318. /*                           "OUT OF MEMORY, " */
  1319.                 curbp->b_flag |= BFTRUNC;
  1320.         }
  1321.         strcat(mesg, TEXT154);
  1322. /*                   "Inserted " */
  1323.         strcat(mesg, int_asc(nline));
  1324.         strcat(mesg, TEXT143);
  1325. /*                   " line" */
  1326.         if (nline > 1)
  1327.                 strcat(mesg, "s");
  1328.         strcat(mesg, "]");
  1329.         mlwrite(mesg);
  1330.  
  1331. out:
  1332.         bp->b_flag |= BFCHG;    /* we have changed      */
  1333.         bp->b_flag &= ~BFINVS;  /* and are not temporary*/
  1334.  
  1335.         /* advance to the next line and mark the window for changes */
  1336.         curwp->w_dotp = lforw(curwp->w_dotp);
  1337.         curwp->w_flag |= WFHARD | WFMODE;
  1338.  
  1339.         /* copy window parameters back to the buffer structure */
  1340.         curbp->b_dotp = curwp->w_dotp;
  1341.         curbp->b_doto = curwp->w_doto;
  1342.         for (cmark = 0; cmark < NMARKS; cmark++) {
  1343.                 curbp->b_markp[cmark] = curwp->w_markp[cmark];
  1344.                 curbp->b_marko[cmark] = curwp->w_marko[cmark];
  1345.         }
  1346.         curbp->b_fcol = curwp->w_fcol;
  1347.  
  1348.         if (s == FIOERR)                        /* False if error.      */
  1349.                 return(FALSE);
  1350.         return(TRUE);
  1351. }
  1352. /*}}}*/
  1353.  
  1354.